﻿
using Bettzueche.RLLibrary.Types;

namespace Bettzueche.RLLibrary.Component {

    ///// <summary>
    ///// Marker interface vor an <see cref="IEnvironment{S,A,R}"/>.
    ///// </summary>
    //public interface IEnvironment
    //{
    //    //double DoAction(IAction a, out IState nextState);
    //}

    

    public interface IEnvironment {

        ///// <summary>
        ///// Gets the current state.
        ///// </summary>
        ///// <value>
        ///// The state.
        ///// </value>
        //IState State { get; }

        /// <summary>
        /// Gibt an, ob der aktuelle Zustand ein Endzustand ist.
        /// </summary>
        bool IsFinal { get; }

        /// <summary>
        /// Inits the environment.
        /// </summary>
        /// <param name="specifications">The specifications.</param>
        void Init(string specifications);

        /// <summary>
        /// Does the action.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="nextState">next State.</param>
        /// <returns>Reward for performing the given action</returns>
        double DoAction(IAction action, out IState nextState);
    }

    /// <summary>
    /// Die Umwelt im RL-Modell.
    /// <para>
    /// Ein Agent führt auf/in seiner Umwelt ein Aktion a aus. Die Umwelt (bspw. Sensorik)
    /// teilt den Folgezustand s+ und die Belohnung r mit.
    /// </para>
    /// </summary>
    /// <typeparam name="S">The State-Type, implementing IState</typeparam>
    /// <typeparam name="A">The Action-Type, implementing IAction</typeparam>
    /// <typeparam name="R">Any value type for the reward, e.g. int, double</typeparam>
    public interface IEnvironment<S, A, R> : IEnvironment
        where S : IState
        where A : IAction
        where R : struct
    {
        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <value>
        /// The state.
        /// </value>
        S State { get; }

        /// <summary>
        /// Angegebene Aktion ausführen.
        /// </summary>
        /// <param name="a">auszuführende Aktion</param>
        /// <param name="nextState">Folgezustand (wird gesetzt)</param>
        /// <returns>Belohnung r (Reward)</returns>
        R DoAction(A a, out S nextState);


        /// <summary>
        /// Gibt die ausführbaren Aktionen im angegebenen Zustand.
        /// </summary>
        /// <param name="state">ein Zustand</param>
        /// <returns>Ausführbare Aktionen im Zustand 'state'</returns>
        //ICollection<A> Executables(S state);
    }
}
